package com.example.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.common.Vo.UserVO;
import com.example.common.annotation.LogAnno;
import com.example.common.constant.Const;
import com.example.common.result.Result;
import com.example.controller.base.BaseController;
import com.example.entity.Position;
import com.example.entity.User;
import com.example.entity.UserDepartment;
import com.example.entity.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 前端控制器：用户操作自身数据api
 * </p>
 *
 * @author ptuDai
 * @since 2021-09-13
 */
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    @Autowired
    PasswordEncoder passwordEncoder;

    @GetMapping("/page")
    @PreAuthorize("hasAuthority('sys:user:list')")
    public Result page(int size, int current, String name, Integer departmentId) {
        IPage<UserVO> userPage = new Page<>(current, size);
        return Result.ok().data(this.userService.selectUserPage(userPage, name, departmentId));
    }

    @GetMapping("/info")
    public Result info() {
        UserVO userVo = this.userService.getUserInfoByUserName(SecurityContextHolder.getContext().getAuthentication().getName());
        return Result.ok().data(userVo);
    }

    @LogAnno(operateType = "编辑个人信息")
    @PostMapping("/updateInfo")
    public Result updateInfo(@RequestBody User userInfo) {
        User u = userService.getById(userInfo.getId());
        try {
            this.userService.updateById(userInfo);
            this.redisUtil.del("userDetails:" + u.getUserName());
        }catch (DuplicateKeyException e){
            return Result.unUpdated().message("该用户名已被使用！");
        }
        return Result.update();
    }

    @LogAnno(operateType = "修改密码")
    @PostMapping("/resetPassword")
    public Result resetPassword(@RequestBody Map<String, Object> param) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", SecurityContextHolder.getContext().getAuthentication().getName());
        User user = this.userService.getOne(wrapper);
        boolean matches = this.passwordEncoder.matches((CharSequence) param.get("currentPass"), user.getPassword());
        if (!matches) {
            return Result.error().message("旧密码不正确！");
        }
        user.setPassword(this.passwordEncoder.encode((CharSequence) param.get("password")));
        this.userService.updateById(user);
        redisUtil.del(Const.PREFIX_JWT+ user.getUserName());
        this.redisUtil.del("userDetails:" + user.getUserName());
        return Result.update();
    }

    @LogAnno(operateType = "重置密码")
    @PostMapping("/repass")
    @PreAuthorize("hasAuthority('sys:user:repass')")
    public Result repass(@RequestBody Integer userId) {
        User user = this.userService.getOne(new QueryWrapper<User>().eq("id", userId));
        user.setPassword(this.passwordEncoder.encode(Const.DEFAULT_PASSWORD));
        this.userService.updateById(user);
        redisUtil.del(Const.PREFIX_JWT+ user.getUserName());
        this.redisUtil.del("userDetails:" + user.getUserName());
        return Result.update().message("重置密码成功");
    }

    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:user:edit')")
    public Result info(@PathVariable Integer id) {
        return Result.ok().data(this.userService.getOne(new QueryWrapper<User>().eq("id", id)));
    }

    @LogAnno(operateType = "更新用户信息")
    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:user:edit')")
    public Result update(@RequestBody User user) {
        this.userService.updateById(user);
        redisService.clearUserAuthoritiesInfo(user.getId());
        return Result.update();
    }


    @LogAnno(operateType = "添加用户")
    @PostMapping("/create")
    @PreAuthorize("hasAuthority('sys:user:add')")
    @Transactional(rollbackFor = Exception.class)
    public Result create(@RequestBody User user) {
        // 设置初始密码
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        user.setPassword(bCryptPasswordEncoder.encode(Const.DEFAULT_PASSWORD));
        final Integer positionId = positionService.getOne(new QueryWrapper<Position>().orderByDesc("level")).getId();
        user.setPositionId(positionId);
        try {
            userService.save(user);
        }catch (DuplicateKeyException e){
            return Result.error().message("用户名已被使用！");
        }
        return Result.created();
    }


    @LogAnno(operateType = "删除用户")
    @PostMapping("/remove")
    @PreAuthorize("hasAuthority('sys:user:del')")
    @Transactional(rollbackFor = Exception.class)
    public Result remove(@RequestBody List<Integer> ids) {
        if (this.userService.deleteUsers(ids)) {
            ids.forEach(id->{
                userDepartmentService.remove(new QueryWrapper<UserDepartment>().eq("user_id",id));
                userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id",id));
                redisService.clearUserAuthoritiesInfo(id);
            });
            return Result.deleted();
        } else {
            return Result.unDeleted();
        }
    }

    @LogAnno(operateType = "分配部门")
    @PostMapping("/userDepartment")
    @PreAuthorize("hasAuthority('sys:user:department')")
    public Result userDepartment(@RequestBody UserDepartment ud) {
        userDepartmentService.remove(new QueryWrapper<UserDepartment>().eq("user_id", ud.getUserId()));
        if (ud.getDepartmentId() == null || userDepartmentService.save(ud)) {
            return Result.ok().message("分配成功");
        }
        return Result.unUpdated();
    }

    /**
     * 分配角色
     * @return
     */
    @LogAnno(operateType = "分配角色")
    @PostMapping("/userRole/{userId}")
    @PreAuthorize("hasAuthority('sys:user:role')")
    @Transactional(rollbackFor = Exception.class)
    public Result userRole(@PathVariable Integer userId, @RequestBody Integer[] roleIds) {
        List<UserRole> userRoles = new ArrayList<>();
        Arrays.stream(roleIds).forEach(roleId -> {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(userId);
            userRoles.add(userRole);
        });
        userRoleService.remove(new QueryWrapper<UserRole>().eq("user_id", userId));
        userRoleService.saveBatch(userRoles);
        // 清除权限信息
        redisService.clearUserAuthoritiesInfo(userId);
        return Result.ok().message("分配成功");
    }

    /**
     * 分配职位
     * @return
     */
    @LogAnno(operateType = "分配职位")
    @PostMapping("/userPosition")
    @PreAuthorize("hasAuthority('sys:user:position')")
    public Result userPosition(@RequestBody User user){
        if (userService.updateById(user)){
            return Result.ok().message("分配成功");
        }
        return Result.error();
    }

}
